/*//////////////////////////////////////////////////////////////


  2048小游戏
  作者:农雷

  2048Game
  author:Ray

//////////////////////////////////////////////////////////////*/


//Global variables
var BORDER_WIDTH = 10;
var STATUS_NORMAL = 0;
var STATUS_MERGE = 1;

var mycanvas;
var context;
var chessboard = new Array(16);
var pieceColor = new Array("#CCC0B3", "#EEE4DA","#EDE0C8",  // 0 2 4
                           "#F2B179", "#F59563", "#F67C5F", // 8 16 32
                           "#F65E3B", "#EDCF72", "#EDCC61", // 64 128 256
                           "#EDC850", "#E6C43E", "#FFA64A", // 512 1024 2048
                           "#F83D38", "#AAB767", "#A4B74E", // 4096 8192 16384
                           "#6BB2D0", "#579CD7", "#1081C7");// 32768 65536 131072

var cellPaddingX = new Array(0,35,35,
                             35,20,20,
                             20,12,12,
                             12,8,8,
                             8,8,10,
                             10,10,10);

var cellPaddingY = new Array(0, 70, 70,
                             70, 70, 70,
                             70, 65, 65,
                             65, 62, 62,
                             62, 62, 60,
                             60, 60, 58);

var cellFontColor = new Array("#776E65", "#776E65", "#776E65",
                              "#F9F6F2", "#F9F6F2", "#F9F6F2",
                              "#F9F6F2", "#F9F6F2", "#F9F6F2",
                              "#F9F6F2", "#F9F6F2", "#F9F6F2",
                              "#F9F6F2", "#F9F6F2", "#F9F6F2",
                              "#F9F6F2", "#F9F6F2", "#F9F6F2");

var cellFontSize = new Array("50px","50px","50px",
                             "50px","50px","50px",
                             "50px","45px","45px",
                             "45px","38px","38px",
                             "38px","38px","30px",
                             "30px","30px","25px");

var pieceClass = {
        key : -1,
        exponential : -1,
        x : -1,
        y : -1,
        status : STATUS_NORMAL,
    };
var canMove = false;
var currentScore = 0;
var bestScore = 0;
var cookiesAliveDay = 1;
var imdeath = false;
var opponent = "";
var opponentID = -1;
var opponentAlive;
var wait;
var waitNow = true;
//app start
$(function(){
    /**net work**/
    startnetwork();
    waitOpponent();
    $("#winbar").hide();
    /**net work end**/

    //install the keyboard event listener
    
    document.onkeydown=jumpPage;
    createCanvas();
    //get bestScore
    bestScore = parseInt($("#bestscore").attr('bestscore'));
    //new game or continue
    if(getCookie("2048game_net_") == "save"){
        initGameEnvironmentByCookies();
    }
    else{
        initialzationCookies();
        initGameEnvironment();
    }
    //event listener
    $("#resetgame").click(function(){
        if(window.confirm('Are you sure to reset the game?')){
            //resetTheGame();
            return true;
        }else{
            return false;
        }
    });
    sentData();
    getData();
});
/*
 * Func：initialization the canvas
 */
function createCanvas()
{
    mycanvas = document.getElementById("gamecanvas");
    context = mycanvas.getContext("2d");
}
/*
 * Func：initialization the environment before the game start
 */
function initGameEnvironment()
{
    var index = 0;
    for (i=0;i<chessboard.length/4;i++)
    {
        for (j=0;j<chessboard.length/4;j++)
        {
            var pElem = Object.create(pieceClass);
            pElem.key = index;
            pElem.exponential = 0;
            pElem.x = j*110 + BORDER_WIDTH;
            pElem.y = i*110 + BORDER_WIDTH;
            pElem.status = STATUS_NORMAL;
            chessboard[index] = pElem;
            //console.log(chessboard[index]);//ie不支持console对象，firefox，chrome都支持 
            //set cookies
            setCookie('piece_net_'+index, 0, cookiesAliveDay);
            index++;
        }
    }
    //initialzation the game
    setNewPiece();
    setNewPiece();
    currentScore = 0;
    setCookie("currentScore_net_", currentScore, cookiesAliveDay);
    setCookie("bestScore_net_", bestScore, cookiesAliveDay);

    //paint the chessboard
    //console.log(chessboard[piece.key]);
    paintChessboard();
}
/*
 * Func：initialization the environment by cookies
 */
function initGameEnvironmentByCookies()
{
    var index = 0;
    for (i=0;i<chessboard.length/4;i++)
    {
        for (j=0;j<chessboard.length/4;j++)
        {
            var pElem = Object.create(pieceClass);
            pElem.key = index;
            var exp = getCookie("piece_net_"+index);
            pElem.exponential = parseInt(exp);
            pElem.x = j*110 + BORDER_WIDTH;
            pElem.y = i*110 + BORDER_WIDTH;
            pElem.status = STATUS_NORMAL;
            chessboard[index] = pElem;
            //console.log(chessboard[index]);//ie不支持console对象，firefox，chrome都支持 
            index++;
        }
    }
    currentScore = parseInt(getCookie("currentScore_net_"));
    bestScore = parseInt(getCookie("bestScore_net_"));
    printChessboard();
    //paint the chessboard
    paintChessboard();
}
/**
 * Func : draw a image in canvas by params[url]
 */
function setNewPiece()
{
    var piece = generatePiece();
    chessboard[piece.key] = piece;
    setCookie('piece_net_'+piece.key, piece.exponential, cookiesAliveDay);
}
/**
 * Func : draw a image in canvas by params[url]
 */
function drawImage(url)
{
    var img = new Image();
    img.onload = function(){
        context.drawImage(img, 0, 0);
    };
    img.src = url;
}
/**
 * Func : draw the 2048 piece in canvas by params[position, exponential]
 * params :
 *          position : the position of current piece what be draw now; it range (0~15);
 *          exponential : the exponential of piece; such as 2048(2`11)'s exponential is 11
 */
function drawRect(elem)
{
    context.fillStyle = pieceColor[elem.exponential];
    context.fillRect(elem.x,elem.y,100,100);
    if(elem.exponential !== 0)
    {
        context.font = cellFontSize[elem.exponential] + " Helvetica";
        context.fillStyle = cellFontColor[elem.exponential];
        context.fillText(Math.pow(2, elem.exponential), elem.x + cellPaddingX[elem.exponential], elem.y + cellPaddingY[elem.exponential]);
    }
}
/**
 * Func : Generate the piece
 */
function generatePiece()
{
    //find a empty place
    var index = getRandomNum(0,15);
    while(!isEmptyPlace(index))
    {
        index = getRandomNum(0,15);
    }
    //rand the exponential of this piece (1->75% , 2->25%)
    var exponential = getRandomNum(1,100);
    if(exponential <= 15)//15% come out a piece what exponential = 2
    {
        exponential = 2;
    }
    else
    {
        exponential = 1;
    }
    var pElem = Object.create(pieceClass);
    pElem.key = index;
    pElem.exponential = exponential;
    pElem.x = chessboard[index].x;
    pElem.y = chessboard[index].y;
    pElem.status = STATUS_NORMAL;

    return pElem;
}

/**
 * Func : return the boolean of wether it is a empty place
 */
function isEmptyPlace(num)
{
    return (chessboard[num].exponential === 0);
}
/**
 * Func : Get the RandNum between params[Min] and params[Max]
 */
function getRandomNum(Min,Max)
{
    var Range = Max - Min;
    var Rand = Math.random();
    return(Min + Math.round(Rand * Range));
}
function resetStatus()
{
    for (i=0;i<chessboard.length;i++)
    {
        chessboard[i].status = STATUS_NORMAL;
    }
}
/**
 * Func : reset whole game
 */
function resetTheGame(){
    initGameEnvironment();
}
/**
 * Func : handle keyboard events
 */
function jumpPage(e) {
    var keyword;
    if(navigator.userAgent.indexOf('Firefox') >= 0){
        keyword = e.which;
    } else {
        keyword = event.keyCode;
    }
    if (keyword==37){
        gameProcess('left');
        return false;
    }
    if (keyword==38){
       gameProcess('up');
        return false;
    }
    if (keyword==39){
       gameProcess('right');
        return false;
    }
    if (keyword==40){
       gameProcess('down');
        return false;
    }
}
/**
 * Func : game process
 */
function gameProcess(direction){
    move(direction);
    if(canMove === true){
        resetStatus();
        setNewPiece();
        canMove = false;
    }
    youAreDeath();
    paintChessboard();
}
/**
 * Func : game process
 */
function youAreDeath(){
    var death = true;
    for(i=0;i<chessboard.length;i++)
    {
        if(chessboard[i].exponential === 0)
        {
            death = false;
        }
    }
    if(death){
        if(canMerge('up') || canMerge('down') || canMerge('left') || canMerge('right')){
            death = false;
        }
    }
    if(death){
        updateDeath();
        alert("you are death, waiting the "+ opponent + " end his game.");
    }
}
/**
 * Func : ajax update score
 */
function updateScore()
{
    //alert($("#resetgame").attr('url'));
    var urlArg = $("#resetgame").attr('url');
    var dataArg = "bestScore="+bestScore;
    var dataTypeArg = "text";
    var successArg = function(data){
        //alert(data);
    };
    //ajaxConstruction(urlArg, dataArg, dataTypeArg, successArg);
}
function updateDeath()
{
    //alert($("#resetgame").attr('url'));
    var urlArg = $("#resetgame").attr('url');
    var dataArg = "death="+bestScore;
    var dataTypeArg = "text";
    var successArg = function(data){
    };
    ajaxConstruction(urlArg, dataArg, dataTypeArg, successArg);
}
function updateNetScore(scoreEnd)
{
    //alert($("#resetgame").attr('url'));
    var urlArg = $("#resetgame").attr('url');
    var dataArg = "scoreEnd="+scoreEnd+"&id="+opponentID;
    var dataTypeArg = "text";
    var successArg = function(data){
        //alert(data);
    };
    ajaxConstruction(urlArg, dataArg, dataTypeArg, successArg);
}
/**
 * Func : find merge , return the boolean of wether can merge
 */
function canMerge(direction)
{
    var index = 0;
    for (i=0;i<chessboard.length/4;i++){
        for (j=0;j<chessboard.length/4,index < 16;j++,index++){
            var result = findSameExp(chessboard[index],direction);
            if(result === null){
            }
            else{
                return true;
            }
        }
    }
    return false;
}
/**
 * Func : paint the chessboard
 */
function move(direction)
{
    if(direction == "left" || direction == "up"){
        var index = 0;
        for (i=0;i<chessboard.length/4;i++){
            for (j=0;j<chessboard.length/4,index < 16;j++,index++){
                if(chessboard[index].exponential === 0 || chessboard[index].status === STATUS_MERGE){
                    continue;
                }
                loopContent(index,direction);
            }
        }
    }
    if(direction == "right" || direction == "down"){
        var _index = 15;
        for (i=0;i<chessboard.length/4;i++){
            for (j=0;j<chessboard.length/4,_index >= 0;j++,_index--){
                if(chessboard[_index].exponential === 0 || chessboard[_index].status === STATUS_MERGE){
                    continue;
                }
                loopContent(_index,direction);
            }
        }
    }
   // fixTheDelayOfmove(direction);
}
function loopContent(index,direction)
{
    var result = findSameExp(chessboard[index],direction);
    var place = findEmptyPlace(chessboard[index],direction);
    if(result === null){
        if(place !== null){
            canMove = true;
            chessboard[place].exponential = chessboard[index].exponential;
            chessboard[index].exponential = 0;
            setCookie('piece_net_'+chessboard[place].key, chessboard[place].exponential, cookiesAliveDay);
            setCookie('piece_net_'+chessboard[index].key, chessboard[index].exponential, cookiesAliveDay);
        }
    }
    else{
        canMove = true;
        chessboard[result].exponential++;
        currentScore += Math.pow(2,chessboard[result].exponential);
        setCookie("currentScore_net_", currentScore, cookiesAliveDay);
        if(currentScore > bestScore){
            bestScore = currentScore;
            setCookie("bestScore_net_", bestScore, cookiesAliveDay);
            updateScore();
        }
        chessboard[result].status = STATUS_MERGE;
        chessboard[index].exponential = 0;
        setCookie('piece_net_'+chessboard[result].key, chessboard[result].exponential, cookiesAliveDay);
        setCookie('piece_net_'+chessboard[index].key, chessboard[index].exponential, cookiesAliveDay);
    }
}
function fixTheDelayOfmove(direction)
{
    var count = 1;
    while(count !== 0)
    {
        var index = 0;
        count = 0;
        for (i=0;i<chessboard.length/4;i++){
            for (j=0;j<chessboard.length/4,index < 16;j++,index++){
                var place = findEmptyPlace(chessboard[index],direction);
                if(place !== null){
                    canMove = true;
                    count++;
                    chessboard[place].exponential = chessboard[index].exponential;
                    chessboard[index].exponential = 0;
                }
            }
        }
    }
}
/**
 * Func : find same
 * Params:
 *          elem : chessboard elem
 *          direction : up down left right
 * Return: index of the same piece
 */
function findSameExp(elem, direction){
    var indexY = Math.floor(elem.key / 4);
    var indexX = elem.key - indexY * 4;
    var key = elem.key;
    if(direction == "left"){
        if((key % 4) === 0 || elem.exponential === 0){
            return null;
        }
        key--;
        for(i=indexX-1;i>=0;i--,key--){
            if(chessboard[key].exponential === 0){
                continue;
            }
            if(chessboard[key].exponential === elem.exponential && chessboard[key].status === STATUS_NORMAL){
                return key;
            }
            else{
                return null;
            }
        }
        return null;
    }
    else if(direction == "right"){
        if((key % 4) === 3 || elem.exponential === 0){
            return null;
        }
        key++;
        for(i=indexX+1;i<4;i++,key++){
            if(chessboard[key].exponential === 0){
                continue;
            }
            if(chessboard[key].exponential === elem.exponential && chessboard[key].status === STATUS_NORMAL){
                return key;
            }
            else{
                return null;
            }
        }
        return null;
    }
    else if(direction == "up"){
        if(key < 4 || elem.exponential === 0){
            return null;
        }
        key-=4;
        for(i=indexY-1;i>=0;i--,key-=4){
            if(chessboard[key].exponential === 0){
                continue;
            }
            if(chessboard[key].exponential === elem.exponential && chessboard[key].status === STATUS_NORMAL){
                return key;
            }
            else{
                return null;
            }
        }
        return null;
    }
    else{
        if(key > 11 || elem.exponential === 0){
            return null;
        }
        key+=4;
        for(i=indexY+1;i<4;i++,key+=4){
            if(chessboard[key].exponential === 0){
                continue;
            }
            if(chessboard[key].exponential === elem.exponential && chessboard[key].status === STATUS_NORMAL){
                return key;
            }
            else{
                return null;
            }
        }
        return null;
    }
}

/**
 * Func : find empty place to go
 * Params:
 *          elem : chessboard elem
 *          direction : up down left right
 * Return: index of the same piece
 */
function findEmptyPlace(elem, direction)
{
    var indexY = Math.floor(elem.key / 4);
    var indexX = elem.key - indexY * 4;
    var key = elem.key;
    var result = null;
    if(direction == "left"){
        if((key % 4) === 0 || elem.exponential === 0){
            return null;
        }
        key--;
        for(i=indexX-1;i>=0;i--,key--){
            if(chessboard[key].exponential !== 0){
                break;
            }
            else{
                result = key;
            }
        }
        return result;
    }
    else if(direction == "right"){
        if((key % 4) === 3 || elem.exponential === 0){
            return null;
        }
        key++;
        for(i=indexX+1;i<4;i++,key++){
            if(chessboard[key].exponential !== 0){
                break;
            }
            else{
                result = key;
            }
        }
        return result;
    }
    else if(direction == "up"){
        if(key < 4 || elem.exponential === 0){
            return null;
        }
        key-=4;
        for(i=indexY-1;i>=0;i--,key-=4){
            if(chessboard[key].exponential !== 0){
                break;
            }
            else{
                result = key;
            }
        }
        return result;
    }
    else{
        if(key > 11 || elem.exponential === 0){
            return null;
        }
        key+=4;
        for(i=indexY+1;i<4;i++,key+=4){
            if(chessboard[key].exponential !== 0){
                break;
            }
            else{
                result = key;
            }
        }
        return result;
    }
}
/**
 * Func : paint the chessboard
 */
function paintChessboard()
{
    for (i=0;i<chessboard.length;i++)
    {
        drawRect(chessboard[i]);
    }
    //update the score
    $("#score").text(currentScore);
    $("#bestscore").text(bestScore);
}

/*
 * Func：initialization the cookies
 */
function initialzationCookies(){
    setCookie('2048game_net_','save',cookiesAliveDay);
}

/*
 * Func：print the chessboard
 */
function printChessboard()
{
    for (i=0;i<chessboard.length;i++)
    {
        console.log(chessboard[i]);
    }
}

function startnetwork()
{
    var urlArg = $("#resetgame").attr('url');
    var dataArg = "netstart=1";
    var dataTypeArg = "text";
    var successArg = function(data){
 //       alert(data);
    };
    ajaxConstruction(urlArg, dataArg, dataTypeArg, successArg);
}

function waitOpponent()
{
    var urlArg = $("#resetgame").attr('url');
    var dataArg = "wait=1";
    var dataTypeArg = "text";
    var successArg = function(data){
        if(data == "success")
        {
            waitNow = false;
            clearTimeout(wait);
            $("#stopact").hide();
            $("#waitbar").hide();
            resetTheGame();
        }
    };
    ajaxConstruction(urlArg, dataArg, dataTypeArg, successArg);
    wait = setTimeout(waitOpponent, 1000);
}
function sentData()
{
    if(waitNow === false){
        var urlArg = $("#resetgame").attr('url');
        var imgURI = mycanvas.toDataURL('image/png');
        var dataArg = "sentdata=1&img="+filter(imgURI)+"&score="+currentScore;
        var dataTypeArg = "text";
        var successArg = function(data){
            //alert(data);
        };
        ajaxConstruction(urlArg, dataArg, dataTypeArg, successArg);
    }
    setTimeout(sentData, 2000);
}
function getData()
{
    if(waitNow === false){
        var urlArg = $("#resetgame").attr('url');
        var dataArg = "getdata=1";
        var dataTypeArg = "json";
        var successArg = function(data){
            $("#opponent-img").attr("src", data.img);
            $("#opponent-score").html(data.score);
            $("#opponent-user").html(data.user);
            opponent = data.user;
            if(opponentID == -1){
                opponentID = data.id;
            }
            opponentAlive = data.death;
            if(data.imdeath == 1 && opponentAlive == 1 && data.alldeath != 1){
                var scoreEnd = 0;
                $("#stopact").show();
                $("#winbar").show();
                if(parseInt(data.score) < parseInt(data.iscore)){
                    scoreEnd = 1;
                    $("#gameEnd").html("You Win !");
                    updateNetScore(scoreEnd);
                } else if (parseInt(data.score) > parseInt(data.iscore)){
                    $("#gameEnd").html("You Lost !");
                    scoreEnd = 2;
                    updateNetScore(scoreEnd);
                } else {
                    scoreEnd = 3;
                    $("#gameEnd").html("Deuce !");
                    updateNetScore(scoreEnd);
                }
                endTheGame();
            }
            else if(data.alldeath == 1){
                $("#stopact").show();
                $("#winbar").show();
                if(parseInt(data.score) < parseInt(data.iscore)){
                    $("#gameEnd").html("You Win !");
                } else if (parseInt(data.score) > parseInt(data.iscore)){
                    $("#gameEnd").html("You Lost !");
                } else {
                    $("#gameEnd").html("Deuce !");
                }
            }
        };
        ajaxConstruction(urlArg, dataArg, dataTypeArg, successArg);
    }
    setTimeout(getData, 1000);
}
function endTheGame()
{
    var urlArg = $("#resetgame").attr('url');
    var imgURI = mycanvas.toDataURL('image/png');
    var dataArg = "end=1";
    var dataTypeArg = "text";
    var successArg = function(data){
    };
    ajaxConstruction(urlArg, dataArg, dataTypeArg, successArg);
}
function filter(str)
{
    str = str.replace(/\+/g,"%2B");
    str = str.replace(/\&/g,"%26");
    return str;
}
